<script lang="ts" setup>
import { Color } from '@tiptap/extension-color'
import ListItem from '@tiptap/extension-list-item'
import TextStyle from '@tiptap/extension-text-style'
import TextAlign from '@tiptap/extension-text-align'
import TaskList from '@tiptap/extension-task-list'
import TaskItem from '@tiptap/extension-task-item'
import Image from '@tiptap/extension-image'
import GlobalDragHandle from 'tiptap-extension-global-drag-handle'
import StarterKit from '@tiptap/starter-kit'
import { Editor, EditorContent } from '@tiptap/vue-3'
import { FileUpload } from './extensions/FileUpload/FileUpload'
import { onBeforeUnmount } from 'vue'

const editor = new Editor({
  extensions: [
    StarterKit,
    FileUpload,
    Color.configure({ types: [TextStyle.name, ListItem.name] }),
    TextStyle,
    TextAlign.configure({
      types: ['heading', 'paragraph'],
    }),
    TaskList,
    TaskItem,
    Image,
    GlobalDragHandle.configure({
      dragHandleWidth: 20, // default

      // The scrollTreshold specifies how close the user must drag an element to the edge of the lower/upper screen for automatic
      // scrolling to take place. For example, scrollTreshold = 100 means that scrolling starts automatically when the user drags an
      // element to a position that is max. 99px away from the edge of the screen
      // You can set this to 0 to prevent auto scrolling caused by this extension
      scrollTreshold: 100, // default

      // The css selector to query for the drag handle. (eg: '.custom-handle').
      // If handle element is found, that element will be used as drag handle.
      // If not, a default handle will be created
      dragHandleSelector: '.custom-drag-handle', // default is undefined

      // Tags to be excluded for drag handle
      // If you want to hide the global drag handle for specific HTML tags, you can use this option.
      // For example, setting this option to ['p', 'hr'] will hide the global drag handle for <p> and <hr> tags.
      excludedTags: [], // default

      // Custom nodes to be included for drag handle
      // For example having a custom Alert component. Add data-type="alert" to the node component wrapper.
      // Then add it to this list as ['alert']
      //
      customNodes: [],
    }),
  ],
  content: '<p>Hello World!</p>',
})

const insertFile = () => {
  editor.commands.setFileUpload({
    url: 'https://example.com/path/to/file.pdf',
    localId: 'file-123',
  })
}

const insertImage = () => {
  editor.commands.setFileUpload({
    url: 'https://placehold.co/400x200.png',
    localId: 'image-' + Date.now(),
  })
}

onBeforeUnmount(() => {
  editor.destroy()
})
</script>

<template>
  <editor-content :editor="editor" />
  <div class="editor-buttons">
    <button @click="insertFile">插入文件</button>
    <button @click="insertImage">插入图片</button>
    <button
      @click="editor.chain().focus().toggleBold().run()"
      :disabled="!editor.can().chain().focus().toggleBold().run()"
      :class="{ 'is-active': editor.isActive('bold') }"
    >
      加粗
    </button>
    <button
      @click="editor.chain().focus().toggleItalic().run()"
      :disabled="!editor.can().chain().focus().toggleItalic().run()"
      :class="{ 'is-active': editor.isActive('italic') }"
    >
      斜体
    </button>
    <button
      @click="editor.chain().focus().toggleStrike().run()"
      :disabled="!editor.can().chain().focus().toggleStrike().run()"
      :class="{ 'is-active': editor.isActive('strike') }"
    >
      删除线
    </button>
    <button
      @click="editor.chain().focus().toggleCode().run()"
      :disabled="!editor.can().chain().focus().toggleCode().run()"
      :class="{ 'is-active': editor.isActive('code') }"
    >
      代码
    </button>
    <button @click="editor.chain().focus().unsetAllMarks().run()">清除标记</button>
    <button @click="editor.chain().focus().clearNodes().run()">清除节点</button>
    <button
      @click="editor.chain().focus().setParagraph().run()"
      :class="{ 'is-active': editor.isActive('paragraph') }"
    >
      段落
    </button>
    <button @click="editor.chain().focus().unsetTextAlign().run()">左对齐</button>
    <button
      @click="editor.chain().focus().setTextAlign('center').run()"
      :class="{ 'is-active': editor.isActive({ textAlign: 'center' }) }"
    >
      居中
    </button>
    <button
      @click="editor.chain().focus().setTextAlign('right').run()"
      :class="{ 'is-active': editor.isActive({ textAlign: 'right' }) }"
    >
      右对齐
    </button>
    <button
      @click="editor.chain().focus().toggleHeading({ level: 1 }).run()"
      :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }"
    >
      H1
    </button>
    <button
      @click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
      :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }"
    >
      H2
    </button>
    <button
      @click="editor.chain().focus().toggleHeading({ level: 3 }).run()"
      :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }"
    >
      H3
    </button>
    <button
      @click="editor.chain().focus().toggleHeading({ level: 4 }).run()"
      :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }"
    >
      H4
    </button>
    <button
      @click="editor.chain().focus().toggleHeading({ level: 5 }).run()"
      :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }"
    >
      H5
    </button>
    <button
      @click="editor.chain().focus().toggleHeading({ level: 6 }).run()"
      :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }"
    >
      H6
    </button>
    <button
      @click="editor.chain().focus().toggleBulletList().run()"
      :class="{ 'is-active': editor.isActive('bulletList') }"
    >
      无序列表
    </button>
    <button
      @click="editor.chain().focus().toggleOrderedList().run()"
      :class="{ 'is-active': editor.isActive('orderedList') }"
    >
      有序列表
    </button>
    <button
      @click="editor.chain().focus().toggleCodeBlock().run()"
      :class="{ 'is-active': editor.isActive('codeBlock') }"
    >
      代码块
    </button>
    <button
      @click="editor.chain().focus().toggleBlockquote().run()"
      :class="{ 'is-active': editor.isActive('blockquote') }"
    >
      引用
    </button>
    <button @click="editor.chain().focus().setHorizontalRule().run()">水平线</button>
    <button @click="editor.chain().focus().setHardBreak().run()">硬换行</button>
    <button
      @click="editor.chain().focus().undo().run()"
      :disabled="!editor.can().chain().focus().undo().run()"
    >
      撤销
    </button>
    <button
      @click="editor.chain().focus().redo().run()"
      :disabled="!editor.can().chain().focus().redo().run()"
    >
      重做
    </button>
    <button
      @click="editor.chain().focus().setColor('#958DF1').run()"
      :class="{ 'is-active': editor.isActive('textStyle', { color: '#958DF1' }) }"
    >
      紫色
    </button>
  </div>
</template>

<style scoped>
.editor-buttons {
  margin-top: 10px;
  button {
    margin: 4px;
  }
}

button {
  padding: 6px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
}

button:hover {
  background: #f5f5f5;
}
</style>
